package org.spring.core.io.support;

import lombok.Getter;
import org.spring.core.io.InputStreamSource;
import org.spring.core.io.Resource;
import org.tool.core.lang.Assert;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.Charset;

/**
 * 将 {@link Resource} 描述符与特定编码或 {@code Charset} 相结合的持有者，用于从资源中读取。
 *
 * <p>用作支持使用特定编码读取内容的操作的参数，通常通过 {@code java.io.Reader}。
 *
 * @author 李坤
 * @date 2022/4/23 13:35
 */
@Getter
public class EncodedResource implements InputStreamSource {

    private final Charset charset;

    private final String encoding;

    private final Resource resource;

    /**
     * 为给定的 {@code Resource} 创建一个新的 {@code EncodedResource}，而不是指定显式编码或 {@code Charset}。
     *
     * @param resource 要保存的 {@code Resource}（从不 {@code null}）
     */
    public EncodedResource(Resource resource) {
        this(resource, null, null);
    }

    /**
     * 使用指定的 {@code encoding} 为给定的 {@code Resource} 创建一个新的 {@code EncodedResource}。
     *
     * @param resource 要保存的 {@code Resource}（从不 {@code null}）
     * @param encoding 用于从资源中读取的编码
     */
    public EncodedResource(Resource resource, String encoding) {
        this(resource, encoding, null);
    }

    /**
     * 使用指定的 {@code Charset} 为给定的 {@code Resource} 创建一个新的 {@code EncodedResource}。
     *
     * @param resource 要保存的 {@code Resource}（从不 {@code null}）
     * @param charset  用于从资源中读取的 {@code Charset}
     */
    public EncodedResource(Resource resource, Charset charset) {
        this(resource, null, charset);
    }

    private EncodedResource(Resource resource, String encoding, Charset charset) {
        Assert.notNull(resource, "Resource must not be null");

        this.resource = resource;
        this.encoding = encoding;
        this.charset = charset;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return null;
    }

    /**
     * 确定是否需要 {@link Reader} 而不是 {@link InputStream}，
     * 即是否已指定 {@linkplain getEncoding() encoding} 或 {@link getCharset() Charset}。
     *
     * @see #getReader()
     * @see #getInputStream()
     */
    public boolean requiresReader() {
        return (this.encoding != null || this.charset != null);
    }

    /**
     * 使用指定的 {@link getCharset() Charset} 或 {@linkplain getEncoding() 编码}（如果有）打开指定资源的 {@code java.io.Reader}。
     *
     * @throws IOException if opening the Reader failed
     * @see #requiresReader()
     * @see #getInputStream()
     */
    public Reader getReader() throws IOException {
        if (this.charset != null) {
            return new InputStreamReader(this.resource.getInputStream(), this.charset);
        } else if (this.encoding != null) {
            return new InputStreamReader(this.resource.getInputStream(), this.encoding);
        } else {
            return new InputStreamReader(this.resource.getInputStream());
        }
    }

}
